package com.leesche.zcsp.node.web.controller.pay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.leesche.zcsp.node.cache.JedisUtil;
import com.leesche.zcsp.node.net.service.NetService;
import com.leesche.zcsp.node.net.service.data.NetDevice;
import com.leesche.zcsp.node.pay.alipay.service.AlipayService;
import com.leesche.zcsp.node.pay.cmbc.service.CmbcPayService;
import com.leesche.zcsp.node.pay.service.RmPayService;
import com.leesche.zcsp.node.pay.sinopay.service.SinopayService;
import com.leesche.zcsp.node.pay.wecha.data.Message;
import com.leesche.zcsp.node.pay.wecha.data.Oauth2To;
import com.leesche.zcsp.node.pay.wecha.data.XmlParam;
import com.leesche.zcsp.node.pay.wecha.service.PayService;
import com.leesche.zcsp.node.pay.wecha.service.WechatService;
import com.leesche.zcsp.node.pay.wecha.timer.WechatTimer;
import com.leesche.zcsp.node.pay.wecha.utils.SignUtil;
import com.leesche.zcsp.node.pay.wecha.utils.Signature;
import com.leesche.zcsp.node.utils.NetConfig;
import com.leesche.zcsp.node.utils.PayConfig;
import com.leesche.zcsp.node.utils.TenpayUtil;
import com.leesche.zcsp.node.web.constants.Constants;
import com.leesche.zcsp.node.web.model.*;
import com.leesche.zcsp.node.web.service.*;
import com.leesche.zcsp.node.web.service.impl.PubDiscountCodeServiceImpl;
import com.leesche.zcsp.node.web.service.impl.data.read.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 在线支付接口
 * @Autor:reid
 * @Date:2016/11/17
 */
@Controller
@RequestMapping("/pay")
@SuppressWarnings("all")
public class PayController {
    public static final Logger LOGGER = Logger.getLogger(PayController.class);

    private static final String PAY_SUCCESS_VIEW = "pay/success";
    private static final String PAY_FAIL_VIEW = "pay/fail";

    //支付页面访问量统计
    public static int ACCESS_COUNT = 0;
    @Autowired
    SysMemberService sysMemberService;
    @Autowired
    private NetService netService;
    @Autowired
    private PayService payService;
    @Autowired
    private CmbcPayService cmbcPayService;
    @Autowired
    private WechatService wechatService;
    @Autowired
    private AlipayService alipayService;
    @Autowired
    private SinopayService sinopayService;
    @Autowired
    private ServOrderService orderService;
    @Autowired
    private SysNoticeService sysNoticeService;
    @Autowired
    private PubDeviceService pubDeviceService;
    @Autowired
    private PubPlaceService pubPlaceService;
    @Autowired
    private PubDiscountService pubDiscountService;
    @Autowired
    private PubDiscountCodeServiceImpl discountCodeService;
    @Autowired
    private SysUserBusinessInfoService busiService;
    @Autowired
    private RmPayService rmPayService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private PUBConsumptionService pubConsumptionService;

    public synchronized static void setAccessCount(int accessCount) {
        ACCESS_COUNT = accessCount;
    }

    /**
     * 微信&支付宝支付页面跳转
     * @param userAgent 浏览器类型
     * @param shortCode 设备简码
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(value = "/{shortCode}/pay", method = RequestMethod.GET)
    public String payView(@RequestHeader("User-Agent") String userAgent, final @PathVariable("shortCode") String
            shortCode, HttpServletRequest request, ModelMap model) {
        if (payService.isWechatBrower(userAgent)) {
            //微信
            StringBuffer url = new StringBuffer();
            url.append(request.getScheme()).append("://").append(request.getServerName()).append("/node/pay/");
            if (PayConfig.PAY_CHANNEL.equalsIgnoreCase("cmbc")) {
                url.append("minsheng/view/");
            } else {
                url.append("wechatPayView/");
            }
            url.append(shortCode);
            return "redirect:" + wechatService.getWechatRedirectUrl(url.toString());
        } else if (payService.isAlipayBrower(userAgent)) {
            QueryPubDiscountCondition condition = new QueryPubDiscountCondition();
            condition.setPaymenturlcode(shortCode);
            List<PubDiscountDto> list = pubDiscountService.findPubDiscountByShortCode(condition);
            model.put("discounts", list);

            // 读取设备ID
            QueryPubDeviceCondition deviceCondition = new QueryPubDeviceCondition();
            deviceCondition.setMac(shortCode);
            PubDeviceDto pubDeviceDto = pubDeviceService.findByCondition(deviceCondition);

            //设备未绑定
            if (pubDeviceDto == null || pubDeviceDto.getAdminid() == null || pubDeviceDto
                    .getPlaceid() == null || pubDeviceDto.getAdminid().intValue() == 0 || pubDeviceDto.getPlaceid()
                                                                                                      .intValue() ==
                    0) {
                return "pay/unbind";
            }

            //在线支付已禁用
            if (pubDeviceDto.getState() == null || pubDeviceDto.getState().intValue() == 2) {
                return "pay/disable";
            }

            model.put("status", netService.isOnline(pubDeviceDto.getImme()));
            model.put("signal", pubDeviceDto.getDp());
            model.put("deviceId", pubDeviceDto.getDeviceid());
            model.put("disCode", pubDeviceDto.getIsDisCode());
            model.put("payChannel", PayConfig.PAY_CHANNEL);

            // 读取用户LOGO和公司名称
            SysNoticeDto sysNoticeDto = sysNoticeService.findSysNotice(pubDeviceDto.getAdminid().intValue());
            // 如果sysNoticeDto为null 则使用默认的公司名称和LOGO
            if (sysNoticeDto == null) {
                sysNoticeDto = sysNoticeService.getDefaultSysNotice();
            }
            model.put("sysNotice", sysNoticeDto);

            setAccessCount(ACCESS_COUNT + 1);

            if (PayConfig.PAY_CHANNEL.equalsIgnoreCase("sino")) {
                return "pay/alipaySino";
            }
            return "pay/alipay";
        }
        return "pay/errorpay";
    }

    /**
     * 微信支付页面
     */
    @RequestMapping(value = {"wechatPayView/{shortCode}"}, method = RequestMethod.GET)
    public String wechatPayView(@RequestHeader("User-Agent") String userAgent, final @PathVariable("shortCode")
            String shortCode, String code, HttpServletRequest request, ModelMap model) {
        LOGGER.info("code=" + code);
        if (code == null || code.equals("")) {
            return "pay/errorpay";
        }

        Message<Oauth2To> message = wechatService.getOauth(code);
        if (message.getType() == Message.Type.error) {
            LOGGER.error("读取用户信息失败......");
        } else if (message.getType() == Message.Type.success) {
            QueryPubDiscountCondition condition = new QueryPubDiscountCondition();
            condition.setPaymenturlcode(shortCode);
            List<PubDiscountDto> list = pubDiscountService.findPubDiscountByShortCode(condition);
            model.put("discounts", list);

            QueryPubDeviceCondition deviceCondition = new QueryPubDeviceCondition();
            deviceCondition.setMac(shortCode);
            PubDeviceDto pubDeviceDto = pubDeviceService.findByCondition(deviceCondition);
            //设备未绑定
            if (pubDeviceDto == null || pubDeviceDto.getAdminid() == null || pubDeviceDto
                    .getPlaceid() == null || pubDeviceDto.getAdminid().intValue() == 0 || pubDeviceDto.getPlaceid()
                                                                                                      .intValue() ==
                    0) {
                return "pay/unbind";
            }

            //在线支付已禁用
            if (pubDeviceDto.getState() == null || pubDeviceDto.getState().intValue() == 2) {
                return "pay/disable";
            }

            model.put("status", netService.isOnline(pubDeviceDto.getImme()));
            model.put("signal", pubDeviceDto.getDp());
            model.put("deviceId", pubDeviceDto.getDeviceid());
            model.put("disCode", pubDeviceDto.getIsDisCode());
            model.put("payChannel", PayConfig.PAY_CHANNEL);

            // 读取用户LOGO和公司名称
            SysNoticeDto sysNoticeDto = sysNoticeService.findSysNotice(pubDeviceDto.getAdminid().intValue());
            // 如果sysNoticeDto为null 则使用默认的公司名称和LOGO
            if (sysNoticeDto == null) {
                sysNoticeDto = sysNoticeService.getDefaultSysNotice();
            }
            model.put("sysNotice", sysNoticeDto);

            model.put("openid", message.getContent().getOpenid());
            LOGGER.info("openid=" + message.getContent().getOpenid().toString());

            String url = request.getScheme() + "://" + request.getServerName() + request.getRequestURI() + "?" + request
                    .getQueryString();
//            LOGGER.info("wechatPayView.url=" + url);
            model.put("jsret", SignUtil.sign(WechatTimer.JS_TIKET, url));

            setAccessCount(ACCESS_COUNT + 1);

            return "pay/wechatpay";
        }
        return "pay/errorpay";
    }

    /**
     * @param userAgent
     * @param deviceid
     * @param discountid
     * @param openid
     * @param request
     * @return
     * @Description: 微信&支付宝预支付,未使用第三方结算渠道
     */
    @ResponseBody
    @RequestMapping(value = "/prepay", method = RequestMethod.POST)
    public Map<String, Object> prePay(@RequestHeader("User-Agent") String userAgent, Long deviceid, Long discountid,
                                      String openid, HttpServletRequest request) {
        Map<String, Object> map = new HashMap<String, Object>();
        PubDiscount pubDiscount = pubDiscountService.selectByPrimaryKey(discountid);
        PubDevice pubDevice = pubDeviceService.selectByPrimaryKey(deviceid);
        if (pubDiscount != null && pubDevice != null) {
            String orderNo = TenpayUtil.getOrderNo();
            ServOrder order = createServOrder(new PubDeviceDto(pubDevice), new PubDiscountDto(pubDiscount), openid,
                    "original");
            if (orderService.insert(order) > 0) {
                try {
                    if (payService.isWechatBrower(userAgent)) {
                        //微信支付
                        String ip;
                        if (request.getHeader("x-forwarded-for") == null) {
                            ip = request.getRemoteAddr();
                        } else {
                            ip = request.getHeader("x-forwarded-for");
                        }
                        Message<String> message = wechatService.prePay(order, ip, openid, "JSAPI");
                        if (message.getType() == Message.Type.success) {
                            LOGGER.info("微信预支付返回结果:prepay_id=" + message.getContent());
                            map.put("appId", PayConfig.appid);
                            map.put("timeStamp", SignUtil.create_timestamp());
                            map.put("nonceStr", SignUtil.getRandomStringByLength(32));
                            map.put("package", "prepay_id=" + message.getContent());
                            map.put("signType", "MD5");
                            map.put("paySign", Signature.getSign(map));
                        }
                        map.put("message", message);
                    } else if (payService.isAlipayBrower(userAgent)) {
                        //支付宝支付
                        map.put("orderinfo", alipayService.orderAlipay(order));
                        map.put("message", Message.success("下单成功", new Object[0]));
                    }
                } catch (Exception e) {
                    LOGGER.error(e.getMessage());
                }
            }
        }
        return map;
    }

    /**
     * 支付宝单局支付
     * @param userAgent
     * @param deviceid
     * @param discountid
     * @param model
     * @param request
     * @return
     */
    @RequestMapping(value = "{deviceid}/{discountid}/preSinglePayInAlipay", method = RequestMethod.GET)
    public String preSinglePayInAlipay(@RequestHeader("User-Agent") String userAgent, final @PathVariable("deviceid")
            Long deviceid, final @PathVariable("discountid") Long discountid, ModelMap model, HttpServletRequest
            request) {
        if (payService.isAlipayBrower(userAgent)) {
            PubDiscount pubDiscount = pubDiscountService.selectByPrimaryKey(discountid);
            PubDevice pubDevice = pubDeviceService.selectByPrimaryKey(Long.valueOf(deviceid));
            if (pubDiscount != null) {
                ServOrder order = createServOrder(new PubDeviceDto(pubDevice), new PubDiscountDto(pubDiscount), "",
                        "original");
                if (orderService.insert(order) > 0) {
                    model.put("orderinfo", alipayService.orderAlipay(order));
                    model.put("status", netService.isOnline(pubDevice.getImme()));
                    return "pay/alipaySingle";
                }
            }
        } else {
            return "pay/errorpay";
        }

        return "pay/errorpay";
    }

    /**
     * @param request
     * @param response
     * @return
     * @throws IOException
     * @Description: 微信扫码支付
     */
    @ResponseBody
    @RequestMapping(value = "/onScanPay", method = RequestMethod.POST)
    public String onScanPay(HttpServletRequest request, HttpServletResponse response) throws IOException {
        XmlParam param = new XmlParam(request.getInputStream());
        Message<String> message = null;
        String productid = param.getParam("product_id"); // productid = deviceid-discountid;
        String data[] = productid.split(Constants.SPILTTMARK);
        String deviceid = data[0];
        String discountid = data[1];
        PubDiscount pubDiscount = pubDiscountService.selectByPrimaryKey(Long.valueOf(discountid));
        PubDevice pubDevice = pubDeviceService.selectByPrimaryKey(Long.valueOf(deviceid));
        ServOrder order = createServOrder(new PubDeviceDto(pubDevice), new PubDiscountDto(pubDiscount), param
                .getParam("openid"), "original");
        if (orderService.insert(order) > 0) {
            String ip = "";
            if (request.getHeader("x-forwarded-for") == null) {
                ip = request.getRemoteAddr();
            } else {
                ip = request.getHeader("x-forwarded-for");
            }
            message = wechatService.prePay(order, ip, param.getParam("openid"), "NATIVE");
        }

        XmlParam res = wechatService
                .onScan(param.getParam("nonce_str"), message, TenpayUtil.getCharacterEncoding(request, response));
        return res.toString();
    }

    /**
     * @param request
     * @return
     * @throws IOException
     * @Description: 微信支付回调
     */
    @ResponseBody
    @RequestMapping(value = "/notify", method = {RequestMethod.POST, RequestMethod.GET})
    public String notifyWechatPay(HttpServletRequest request) throws IOException {
        LOGGER.info("wechat pay notify......");
        String resXml;

        try {
            XmlParam param = new XmlParam(request.getInputStream());
            String return_code = param.getParam("return_code");

            if (return_code.equals("SUCCESS")) {
                String result_code = param.getParam("result_code");
                String orderNo = param.getParam("out_trade_no");//订单号
                String transactionId = param.getParam("transaction_id");//交易流水号
                String time_end = param.getParam("time_end");//订单号
                ServOrder servOrder = orderService.findServOrderByOrderNo(orderNo);
//                LOGGER.info("servorder id=" + servOrder.getOrderid());
                PubDevice pubDevice = pubDeviceService.selectByPrimaryKey(servOrder.getDeviceid());
//                LOGGER.info("deviceId=" + pubDevice.getDeviceid());

                Date now = new Date();
                servOrder.setTransactionId(transactionId);
                if (result_code.equals("SUCCESS")) {
                    servOrder.setTradeState(Constants.TRADE_STATE_SUCCESS);
                    servOrder.setTradeStateDesc("交易成功");
                    servOrder.setTimeEnd(now);
                    orderService.updateByPrimaryKey(servOrder);
                    //支付成功才调用出币流程
                    LOGGER.info("准备启动阿里IOT 发送指令给设备........");
                    netService.sendClientBuy(pubDevice, servOrder.getCashFee() / 100, servOrder
                            .getCoin(), PayConfig.PAY_WECHAT, servOrder);
                } else {
                    servOrder.setTradeState(Constants.TRADE_STATE_PAYERROR);
                    servOrder.setTradeStateDesc("交易失败");
                    servOrder.setTimeEnd(now);
                    orderService.updateByPrimaryKey(servOrder);
                }

//                orderService.updateServOrderByOrderNo(new UpdateServOrderCommad(Constants.WECHAT_SUCCESS,
//                        param.getParam("transaction_id"), param.getParam("out_trade_no")));
            }
            resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml" +
                    "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "> ";
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
            resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理失败]]></return_msg></xml> ";
        }
        LOGGER.info("resXml=" + resXml);
        return resXml;
    }

    /**
     * 支付宝回调
     * @param out_trade_no
     * @param trade_no
     * @param trade_status
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/notifyAlipay", method = RequestMethod.POST)
    public String notifyAlipay(String out_trade_no, String trade_no, String trade_status, HttpServletRequest request,
                               HttpServletResponse response) {
        return alipayService.notifyAlipay(request.getParameterMap(), out_trade_no, trade_no, trade_status).getContent();
    }

    @RequestMapping(value = "/{shortCode}/pay2", method = RequestMethod.GET)
    public String payView2(@RequestHeader("User-Agent") String userAgent, final @PathVariable("shortCode") String
            shortCode, HttpServletRequest request, ModelMap model) {
        if (payService.isWechatBrower(userAgent)) {
            StringBuffer url = new StringBuffer();
            url.append(request.getScheme()).append("://").append(request.getServerName()).append("/node/pay/");
            url.append("minsheng/view/");
            url.append(shortCode);
            return "redirect:" + wechatService.getWechatRedirectUrl(url.toString());
        } else if (payService.isAlipayBrower(userAgent)) {
            QueryPubDiscountCondition condition = new QueryPubDiscountCondition();
            condition.setPaymenturlcode(shortCode);
            List<PubDiscountDto> list = pubDiscountService.findPubDiscountByShortCode(condition);
            model.put("discounts", list);

            // 读取设备ID
            QueryPubDeviceCondition deviceCondition = new QueryPubDeviceCondition();
            deviceCondition.setMac(shortCode);
            PubDeviceDto pubDeviceDto = pubDeviceService.findByCondition(deviceCondition);
            model.put("status", netService.isOnline(pubDeviceDto.getImme()));
            model.put("signal", pubDeviceDto.getDp());
            model.put("deviceId", pubDeviceDto.getDeviceid());
            model.put("disCode", pubDeviceDto.getIsDisCode());
            model.put("payChannel", "cmbc");

            // 读取用户LOGO和公司名称
            SysNoticeDto sysNoticeDto = sysNoticeService.findSysNotice(pubDeviceDto.getDeviceid().intValue());
            // 如果sysNoticeDto为null 则使用默认的公司名称和LOGO
            if (sysNoticeDto == null) {
                sysNoticeDto = sysNoticeService.getDefaultSysNotice();
            }
            model.put("sysNotice", sysNoticeDto);

            synchronized (this) {
                ACCESS_COUNT++;
            }

            return "pay/alipay";
        }
        return "pay/errorpay";
    }

    /**
     * 民生支付页面
     */
    @RequestMapping(value = "minsheng/view/{shortCode}", method = RequestMethod.GET)
    public String minshengView(@RequestHeader("User-Agent") String userAgent, final @PathVariable("shortCode")
            String shortCode, String code, HttpServletRequest request, ModelMap model) {
        LOGGER.info("code=" + code);
        if (code == null || code.equals("")) {
            return "pay/errorpay";
        }

        Message<Oauth2To> message = wechatService.getOauth(code);
        if (message.getType() == Message.Type.error) {
            LOGGER.error("读取用户信息失败......");
        } else if (message.getType() == Message.Type.success) {
            QueryPubDiscountCondition condition = new QueryPubDiscountCondition();
            condition.setPaymenturlcode(shortCode);
            List<PubDiscountDto> list = pubDiscountService.findPubDiscountByShortCode(condition);
            model.put("discounts", list);

            QueryPubDeviceCondition deviceCondition = new QueryPubDeviceCondition();
            deviceCondition.setMac(shortCode);
            PubDeviceDto pubDeviceDto = pubDeviceService.findByCondition(deviceCondition);
            //设备未绑定
            if (pubDeviceDto == null || pubDeviceDto.getAdminid() == null || pubDeviceDto.getPlaceid() == null
                    || pubDeviceDto.getAdminid().intValue() == 0 || pubDeviceDto.getPlaceid().intValue() == 0) {
                return "pay/unbind";
            }

            //在线支付已禁用
            if (pubDeviceDto.getState() == null || pubDeviceDto.getState().intValue() == 2) {
                return "pay/disable";
            }

            model.put("status", netService.isOnline(pubDeviceDto.getImme()));
            model.put("signal", pubDeviceDto.getDp());
            model.put("deviceId", pubDeviceDto.getDeviceid());
            model.put("disCode", pubDeviceDto.getIsDisCode());
            model.put("payChannel", "cmbc");

            // 读取用户LOGO和公司名称
            SysNoticeDto sysNoticeDto = sysNoticeService.findSysNotice(pubDeviceDto.getAdminid().intValue());
            // 如果sysNoticeDto为null 则使用默认的公司名称和LOGO
            if (sysNoticeDto == null) {
                sysNoticeDto = sysNoticeService.getDefaultSysNotice();
            }
            model.put("sysNotice", sysNoticeDto);

            model.put("openid", message.getContent().getOpenid());
            LOGGER.info("openid=" + message.getContent().getOpenid().toString());

            String url = request.getScheme() + "://" + request.getServerName() + request.getRequestURI() + "?" + request
                    .getQueryString();
            model.put("jsret", SignUtil.sign(WechatTimer.JS_TIKET, url));

            setAccessCount(ACCESS_COUNT + 1);

            return "pay/wechatpay";
        }
        return "pay/errorpay";
    }

    /**
     * @param userAgent
     * @param deviceid
     * @param discountid
     * @param openid
     * @param request
     * @return
     * @Description: 预支付, 使用民生银行结算渠道
     */
    @ResponseBody
    @RequestMapping(value = "/minsheng/prepay", method = RequestMethod.POST)
    public Map<String, Object> prePayCmbc(@RequestHeader("User-Agent") String userAgent, Long deviceid, Long
            discountid, String openid, HttpServletRequest request) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            PubDiscountDto discountDto = null;
            discountDto = (PubDiscountDto) JedisUtil
                    .hget("discountMap", String.valueOf(discountid), new PubDiscountDto());
            if (discountDto != null && StringUtils.isNotBlank(discountDto.getDiscountid())) {
                LOGGER.info("套餐信息redis 缓存命中......");
            } else {
                LOGGER.info("套餐信息redis 缓存未命中,查询数据库......");
                PubDiscount discount = pubDiscountService.selectByPrimaryKey(discountid);
                discountDto = new PubDiscountDto(discount);
                JedisUtil.hset("discountMap", String.valueOf(discountid), discountDto);
            }

            PubDeviceDto deviceDto = null;
            deviceDto = (PubDeviceDto) JedisUtil.hget("deviceMap", String.valueOf(deviceid), new PubDeviceDto());
            if (deviceDto != null && deviceDto.getDeviceid() != null && deviceDto.getAdminid() != null && deviceDto
                    .getAdminid() != 0) {
                LOGGER.info("设备信息redis 缓存命中......");
            } else {
                LOGGER.info("设备信息redis 缓存未命中,查询数据库......");
                PubDevice device = pubDeviceService.selectByPrimaryKey(deviceid);
                deviceDto = new PubDeviceDto(device);
                JedisUtil.hset("deviceMap", String.valueOf(deviceDto.getDeviceid()), deviceDto);
                JedisUtil.hset("netDeviceMap", String.valueOf(deviceDto.getImme()), new NetDevice(deviceDto
                        .getDeviceid(), deviceDto.getAdminid(), deviceDto.getPlaceid(), deviceDto.getIsonline()));
            }

            if (discountDto != null && deviceDto != null) {
                String orderNo = TenpayUtil.getOrderNo();
                ServOrder order = createServOrder(deviceDto, discountDto, openid, "original");
                if (orderService.insert(order) > 0) {
                    try {
                        if (payService.isWechatBrower(userAgent)) {
                            //微信
                            Message<String> message = cmbcPayService.prePay(order, openid, "wechat");
                            if (message.getType() == Message.Type.success) {
                                JSONObject jsonObj = JSON.parseObject(message.getContent());
                                LOGGER.info("微信预支付返回结果:jsonObj=" + jsonObj.toJSONString());
                                map.put("appId", jsonObj.getString("appId"));
                                map.put("timeStamp", jsonObj.getString("timeStamp"));
                                map.put("nonceStr", jsonObj.getString("nonceStr"));
                                map.put("package", jsonObj.getString("package"));
                                map.put("signType", jsonObj.getString("signType"));
                                map.put("paySign", jsonObj.getString("paySign"));
                            }
                            map.put("message", message);
                        } else if (payService.isAlipayBrower(userAgent)) {
                            //支付宝
                            Message<String> message = cmbcPayService.prePay(order, openid, "alipay");
                            if (message.getType() == Message.Type.success) {
                                map.put("orderinfo", alipayService.orderAlipay(order));
                                map.put("message", Message.success("下单成功", new Object[0]));
                            }
                        }
                    } catch (Exception e) {
                        LOGGER.error(e.getMessage());
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return map;
    }

    /**
     * 民生支付回调接口
     */
    @ResponseBody
    @RequestMapping(value = "/minsheng/callback", method = {RequestMethod.POST, RequestMethod.GET})
    public String cmbcNotify(HttpServletRequest request) {
        LOGGER.info("minsheng pay notify......");
        return cmbcPayService.notify(request.getParameterMap());
    }

    @ResponseBody
    @RequestMapping(value = "/minsheng/query", method = RequestMethod.GET)
    public Message<String> queryOrderStateCmbc(String orderDate, String orderNo) throws Exception {
        return cmbcPayService.queryOrderState(orderDate, orderNo);
    }


    @ResponseBody
    @RequestMapping(value = "/sino/prepay", method = RequestMethod.POST)
    public Map<String, Object> prePaySino(@RequestHeader("User-Agent") String userAgent, Long deviceid, Long
            discountid, String openid, HttpServletRequest request) {
        Map<String, Object> map = new HashMap<String, Object>();
//        PubDiscount pubDiscount = pubDiscountService.selectByPrimaryKey(discountid);
//        PubDevice pubDevice = pubDeviceService.selectByPrimaryKey(deviceid);

        PubDiscountDto discountDto = null;
        discountDto = (PubDiscountDto) JedisUtil.hget("discountMap", String.valueOf(discountid), new PubDiscountDto());
        if (discountDto != null && StringUtils.isNotBlank(discountDto.getDiscountid())) {
            LOGGER.info("套餐信息redis 缓存命中......");
        } else {
            LOGGER.info("套餐信息redis 缓存未命中,查询数据库......");
            PubDiscount discount = pubDiscountService.selectByPrimaryKey(discountid);
            discountDto = new PubDiscountDto(discount);
            //更新到redis
            JedisUtil.hset("discountMap", String.valueOf(discountid), discountDto);
        }

        PubDeviceDto deviceDto = null;
        deviceDto = (PubDeviceDto) JedisUtil.hget("deviceMap", String.valueOf(deviceid), new PubDeviceDto());
        if (deviceDto != null && deviceDto.getDeviceid() != null && deviceDto.getAdminid() != null && deviceDto
                .getAdminid() != 0) {
            LOGGER.info("设备信息redis 缓存命中......");
        } else {
            LOGGER.info("设备信息redis 缓存未命中,查询数据库......");
            PubDevice device = pubDeviceService.selectByPrimaryKey(deviceid);
            deviceDto = new PubDeviceDto(device);
            JedisUtil.hset("deviceMap", String.valueOf(deviceDto.getDeviceid()), deviceDto);
            JedisUtil.hset("netDeviceMap", String.valueOf(deviceDto.getImme()), new NetDevice(deviceDto
                    .getDeviceid(), deviceDto.getAdminid(), deviceDto.getPlaceid(), deviceDto.getIsonline()));
        }

        QuerySysUserBusinessInfoCondition condition = new QuerySysUserBusinessInfoCondition();
        condition.setUserid(deviceDto.getAdminid());
        condition.setQueryAll(true);
        SysUserBusinessInfoDto busiInfoDto = busiService.findByCondition(condition);
        if (busiInfoDto == null) {
            Message<String> message = Message.error("商户未激活!", new Object[0]);
            map.put("message", message);
            return map;
        }
//        LOGGER.info(busiInfoDto.getMerchantnumber() + "--" + busiInfoDto.getMerchantkey());

        ServOrder order = createServOrder(deviceDto, discountDto, openid, "original");
        if (orderService.insert(order) > 0) {
            try {
                String ip;
                if (request.getHeader("x-forwarded-for") == null) {
                    ip = request.getRemoteAddr();
                } else {
                    ip = request.getHeader("x-forwarded-for");
                }

                if (payService.isWechatBrower(userAgent)) {
                    //微信
                    Message<String> message = sinopayService.prePay(order, ip, busiInfoDto, "wechat", false);
                    if (message.getType() == Message.Type.success) {
                        JSONObject jsonObj = JSON.parseObject(message.getContent());
                        LOGGER.info("微信预支付返回结果:jsonObj=" + jsonObj.toJSONString());
                        map.put("appId", jsonObj.getString("appId"));
                        map.put("timeStamp", jsonObj.getString("timeStamp"));
                        map.put("nonceStr", jsonObj.getString("nonceStr"));
                        map.put("package", jsonObj.getString("package"));
                        map.put("signType", jsonObj.getString("signType"));
                        map.put("paySign", jsonObj.getString("paySign"));
                    }
                    map.put("message", message);
                } else if (payService.isAlipayBrower(userAgent)) {
                    Message<String> message = sinopayService.prePay(order, ip, busiInfoDto, "alipay", false);
                    map.put("message", message);
                }
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
        return map;
    }

    /**
     * 翔融支付回调通知
     */
    @ResponseBody
    @RequestMapping(value = "/sino/notify", method = RequestMethod.POST)
    public String notifySinopay(HttpServletRequest request) throws IOException, ParseException {
        LOGGER.info("sino pay notify......");
        return sinopayService.notify(request);
    }

    /**
     * 优惠码支付
     */
    @ResponseBody
    @RequestMapping(value = "/payWithCoupon", method = RequestMethod.POST)
    public String payWithCoupon(Long deviceId, String disCode) {
        PubDevice device = pubDeviceService.selectByPrimaryKey(deviceId);

        QueryPubDiscountCodeCondition condition = new QueryPubDiscountCodeCondition();
        condition.setAdminId(device.getAdminid());
        condition.setDiscountCode(disCode);
//        condition.setCodeState(1);
        PubDiscountCode pubDiscountCode = discountCodeService.selectByModel(condition);
        Date now = new Date();
        if (pubDiscountCode != null) {
            if (pubDiscountCode.getCodestate().intValue() == 2) {
                return "USED";
            }
            if (pubDiscountCode.getIntime().after(now)) {
                return "NOT";
            }
            if (pubDiscountCode.getOuttime().before(now)) {
                return "OUT";
            }

            try {
                pubDiscountCode.setDeviceid(deviceId);
                pubDiscountCode.setCodestate(2);
                pubDiscountCode.setIntdata2(device.getPlaceid().intValue());//场地
                pubDiscountCode.setSdata3(String.valueOf(device.getDevicetypeid()));
                pubDiscountCode.setUpdatetime(new Date());
                discountCodeService.updateByPrimaryKey(pubDiscountCode);

                LOGGER.info("优惠码支付成功,开始发送指令给设备......");
                netService.sendClientBuy(device, 0, pubDiscountCode.getCoin(), NetConfig.PAYTYPE_COUPON, null);
                return "SUCCESS";
            } catch (Exception e) {
                LOGGER.error("PayController 捕获异常...:" + e.getMessage());
                return "ERROR";
            }
        } else {
            return "FAIL";
        }
    }

    /**
     * 支付成功页面
     * @return
     */
    @RequestMapping(value = "/success", method = RequestMethod.GET)
    public String success() {
        return PAY_SUCCESS_VIEW;
    }

    /**
     * 支付失败页面
     * @return
     */
    @RequestMapping(value = "/fail", method = RequestMethod.GET)
    public String fail() {
        return PAY_FAIL_VIEW;
    }

    @RequestMapping(value = "/{shortCode}/memberPay", method = RequestMethod.GET)
    public String memberPay(@RequestHeader("User-Agent") String userAgent, final @PathVariable("shortCode") String
            shortCode, HttpServletRequest request, ModelMap model) {
        StringBuffer url = new StringBuffer();
        url.append(request.getScheme()).append("://").append(request.getServerName()).append("/node/pay/memberPayView/")
           .append(shortCode);

        if (payService.isWechatBrower(userAgent)) {
            return "redirect:" + wechatService.getWechatRedirectUrl(url.toString());
        } else if (payService.isAlipayBrower(userAgent)) {
            return "redirect:" + alipayService.getAlipayRedirectUrl(url.toString());
        }
        return "pay/errorpay";
    }

    @RequestMapping(value = {"memberPayView/{shortCode}"}, method = RequestMethod.GET)
    public String memberPayView(@RequestHeader("User-Agent") String userAgent, final @PathVariable("shortCode")
            String shortCode, String code, String auth_code, HttpServletRequest request, ModelMap model) {
        LOGGER.info("wechat authCode=" + code);
        LOGGER.info("alipay authCode=" + auth_code);

        boolean isWechatBrower = payService.isWechatBrower(userAgent);
        boolean isAlipayBrower = payService.isAlipayBrower(userAgent);

        if (isWechatBrower && StringUtils.isEmpty(code)) {
            return "pay/errorpay";
        }

        if (isAlipayBrower && StringUtils.isEmpty(auth_code)) {
            return "pay/errorpay";
        }

        Message<Oauth2To> message = null;
        if (isWechatBrower) {
            message = wechatService.getOauth(code);
        } else if (isAlipayBrower) {
            message = alipayService.getOauth(auth_code);
        }

        if (message == null || message.getType() == Message.Type.error) {
            LOGGER.error("读取用户信息失败......");
        } else if (message.getType() == Message.Type.success) {
            Date now = new Date();

            QueryPubDiscountCondition condition = new QueryPubDiscountCondition();
            condition.setPaymenturlcode(shortCode);
            List<PubDiscountDto> list = pubDiscountService.findPubDiscountByShortCode(condition);
            model.put("discounts", list);

            QueryPubDeviceCondition deviceCondition = new QueryPubDeviceCondition();
            deviceCondition.setMac(shortCode);
            PubDeviceDto pubDeviceDto = pubDeviceService.findByCondition(deviceCondition);

            //设备未绑定
            if (pubDeviceDto == null || pubDeviceDto.getAdminid() == null || pubDeviceDto
                    .getPlaceid() == null || pubDeviceDto.getAdminid().intValue() == 0 || pubDeviceDto.getPlaceid()
                                                                                                      .intValue() ==
                    0) {
                return "pay/unbind";
            }
            //在线支付已禁用
            if (pubDeviceDto.getState() == null || pubDeviceDto.getState().intValue() == 2) {
                return "pay/disable";
            }
            model.put("device", pubDeviceDto);

            PubPlace place = pubPlaceService.selectByPrimaryKey(pubDeviceDto.getPlaceid());
            model.put("place", place.getAddress());

            SysUser sysUser = sysUserService.selectByPrimaryKey(pubDeviceDto.getAdminid());

            QuerySysMemberCondition memberCondition = new QuerySysMemberCondition();
            if (isWechatBrower) {
                memberCondition.setOpenid(message.getContent().getOpenid());
            } else {
                memberCondition.setAlipayid(message.getContent().getOpenid());
            }
            memberCondition.setAdminid(pubDeviceDto.getAdminid());
            SysMemberDto sysMemberDto = sysMemberService.findByCondition(memberCondition);

//            SysMember sysMember = null;
            if (sysMemberDto != null) {
                model.put("sysMember", sysMemberDto);
            } else {
                SysMember sysMember = new SysMember();
                sysMember.setMemberno(sysUser.getBusinessno());
//                sysMember.setOpenid(message.getContent().getOpenid());
                if (isWechatBrower) {
                    sysMember.setOpenid(message.getContent().getOpenid());
                } else {
                    sysMember.setAlipayid(message.getContent().getOpenid());
                }
                sysMember.setAdminid(pubDeviceDto.getAdminid());
                sysMember.setMobile(sysUser.getMobile());
                sysMember.setCoin(0);
                sysMember.setPoint(0);
                sysMember.setScore(0);
                sysMember.setUpdatetime(now);
                sysMemberService.insert(sysMember);
                model.put("sysMember", sysMember);
            }

            // 读取用户LOGO和公司名称
            SysNoticeDto sysNoticeDto = sysNoticeService.findSysNotice(pubDeviceDto.getAdminid().intValue());
            if (sysNoticeDto == null) {
                sysNoticeDto = sysNoticeService.getDefaultSysNotice();
            }
            model.put("sysNotice", sysNoticeDto);

            model.put("status", netService.isOnline(pubDeviceDto.getImme()));
            model.put("openid", message.getContent().getOpenid());
            if (isWechatBrower) {
//                model.put("openid", message.getContent().getOpenid());
                LOGGER.info("openid=" + message.getContent().getOpenid().toString());
                String url = request.getScheme() + "://" + request.getServerName() + request
                        .getRequestURI() + "?" + request.getQueryString();
                model.put("jsret", SignUtil.sign(WechatTimer.JS_TIKET, url));
                return "pay/memberView";
            } else {
//                model.put("openid", message.getContent().getOpenid());
                return "pay/memberViewAlipay";
            }
        }
        return "pay/errorpay";
    }

    @ResponseBody
    @RequestMapping(value = "/member/prepay", method = RequestMethod.POST)
    public Map<String, Object> prepayMember(@RequestHeader("User-Agent") String userAgent, Long deviceid, Long
            discountid, String openid, HttpServletRequest request) {
        Map<String, Object> map = new HashMap<String, Object>();

        PubDiscount discount = pubDiscountService.selectByPrimaryKey(discountid);
        PubDiscountDto discountDto = new PubDiscountDto(discount);

        PubDevice device = pubDeviceService.selectByPrimaryKey(deviceid);
        PubDeviceDto deviceDto = new PubDeviceDto(device);

        QuerySysUserBusinessInfoCondition condition = new QuerySysUserBusinessInfoCondition();
        condition.setUserid(deviceDto.getAdminid());
        condition.setQueryAll(true);
        SysUserBusinessInfoDto busiInfoDto = busiService.findByCondition(condition);
        if (busiInfoDto == null) {
            Message<String> message = Message.error("商户未激活!", new Object[0]);
            map.put("message", message);
            return map;
        }

        ServOrder order = createServOrder(deviceDto, discountDto, openid, "member");
        if (orderService.insert(order) > 0) {
            try {
                String ip;
                if (request.getHeader("x-forwarded-for") == null) {
                    ip = request.getRemoteAddr();
                } else {
                    ip = request.getHeader("x-forwarded-for");
                }

                if (payService.isWechatBrower(userAgent)) {
                    //微信
                    Message<String> message = sinopayService.prePay(order, ip, busiInfoDto, "wechat", true);
                    if (message.getType() == Message.Type.success) {
                        JSONObject jsonObj = JSON.parseObject(message.getContent());
                        LOGGER.info("微信预支付返回结果:jsonObj=" + jsonObj.toJSONString());
                        map.put("appId", jsonObj.getString("appId"));
                        map.put("timeStamp", jsonObj.getString("timeStamp"));
                        map.put("nonceStr", jsonObj.getString("nonceStr"));
                        map.put("package", jsonObj.getString("package"));
                        map.put("signType", jsonObj.getString("signType"));
                        map.put("paySign", jsonObj.getString("paySign"));
                    }
                    map.put("message", message);
                } else if (payService.isAlipayBrower(userAgent)) {
                    Message<String> message = sinopayService.prePay(order, ip, busiInfoDto, "alipay", true);
                    map.put("message", message);
                }
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
        return map;
    }

    @ResponseBody
    @RequestMapping(value = "/notifyMemberPay", method = RequestMethod.POST)
    public String notifyMemberPay(HttpServletRequest request) {
        return sinopayService.notifyMemberPay(request);
    }

    /**
     * 会员页面余币支付
     */
    @ResponseBody
    @RequestMapping(value = "/member/give", method = RequestMethod.POST)
    public String memberPayGiveCoin(long deviceId, long memberId, int coin) {
        PubDevice pubDevice = pubDeviceService.selectByPrimaryKey(deviceId);
        boolean flag = netService.sendClientBuy(pubDevice, 0, coin, NetConfig.PAYTYPE_GAMECOINBU, null);
        try {
            if (flag) {
                SysMember sysMember = sysMemberService.selectByPrimaryKey(memberId);
                sysMember.setCoin(sysMember.getCoin() - coin);
                sysMemberService.updateByPrimaryKey(sysMember);

                PUBConsumption pubConsumption = new PUBConsumption();
                pubConsumption.setMemberid(memberId);
                pubConsumption.setDeviceid(deviceId);
                pubConsumption.setDevicename(pubDevice.getDevicename());
                pubConsumption.setPlaceid(pubDevice.getPlaceid());
                pubConsumption.setQuantity(coin);
                pubConsumption.setCoin(sysMember.getCoin() - coin);
                pubConsumption.setCtype(2);
                pubConsumption.setResult(1);
                pubConsumption.setResulttext("成功");
                pubConsumptionService.insert(pubConsumption);
                return "success";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "fail";
    }

    @RequestMapping(value = "/alipay/gateway", method = RequestMethod.POST)
    public void verifyAlipayGateWay(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String responseMsg = alipayService.verifyAlipayGateWay(request);
        response.reset();
        response.setContentType("text/xml;charset=GBK");
        PrintWriter printWriter = response.getWriter();
        printWriter.print(responseMsg);
        response.flushBuffer();
    }

    private ServOrder createServOrder(PubDeviceDto pubDevice, PubDiscountDto pubDiscount, String openid, String
            remark) {
//    private ServOrder createServOrder(PubDevice pubDevice, PubDiscount pubDiscount, String openid) {
        Date now = new Date();
        String orderNo = TenpayUtil.getOrderNo();
        ServOrder order = new ServOrder();
        order.setCreatetime(now);
        order.setCashFee(pubDiscount.getMoney() * 100); //存储以分为单位
        order.setCoin(pubDiscount.getCoin());
        order.setDeviceid(pubDevice.getDeviceid());
        order.setDiscountid(Long.valueOf(pubDiscount.getDiscountid()));
        order.setTimeEnd(now);
        order.setTransactionId("");
        order.setTradeStateDesc("下订单");
        order.setTradeState(Constants.TRADE_STATE_NOTPAY);
        order.setOutTradeNo(orderNo);
        order.setOpenid(openid);
        order.setUserid(pubDevice.getAdminid());
        order.setRemark(remark);
        return order;
    }

/*
    @RequestMapping(value = {"/rmPayView/{shortCode}",}, method = RequestMethod.GET)
    public String rmPayView(@RequestHeader("User-Agent") String userAgent,
                            final @PathVariable("shortCode") String shortCode, HttpServletRequest request,
                            ModelMap model) {

        // 优惠信息
        QueryPubDiscountCondition condition = new QueryPubDiscountCondition();
        condition.setPaymenturlcode(shortCode);
        List<PubDiscountDto> list = pubDiscountService.findPubDiscountByShortCode(condition);
        model.put("discounts", list);

        QueryPubDeviceCondition deviceCondition = new QueryPubDeviceCondition();
        deviceCondition.setMac(shortCode);
        PubDeviceDto pubDeviceDto = pubDeviceService.findByCondition(deviceCondition);

        model.put("status", true);//netService.isOnline(pubDeviceDto.getImme())
        model.put("deviceId", pubDeviceDto.getDeviceid());
        model.put("disCode", pubDeviceDto.getIsDisCode());
        LOGGER.info("disCode=" + pubDeviceDto.getIsDisCode());

        // 读取用户LOGO和公司名称
        SysNoticeDto sysNoticeDto = sysNoticeService.findSysNotice(pubDeviceDto.getDeviceid().intValue());
        // 如果sysNoticeDto为null 则使用默认的公司名称和LOGO
        if (sysNoticeDto == null) {
            sysNoticeDto = sysNoticeService.getDefaultSysNotice();
        }
        model.put("sysNotice", sysNoticeDto);

        model.put("openid", PayConfig.RM_OPENID_TEST);

        return "pay/rmpay";
    }

    @ResponseBody
    @RequestMapping(value = "/rm/prepay", method = RequestMethod.POST)
    public Map<String, Object> prePayRM(@RequestHeader("User-Agent") String userAgent, Long deviceid, Long discountid,
                                        String openid, HttpServletRequest request) {

        Map<String, Object> map = new HashMap<String, Object>();
        PubDiscount pubDiscount = pubDiscountService.selectByPrimaryKey(discountid);
        PubDevice pubDevice = pubDeviceService.selectByPrimaryKey(deviceid);
        if (pubDiscount != null && pubDevice != null) {
            String orderNo = TenpayUtil.getOrderNo();
            ServOrder order = createServOrder(new PubDeviceDto(pubDevice), new PubDiscountDto(pubDiscount), openid);
            if (orderService.insert(order) > 0) {
                try {
                    Message<String> message = rmPayService.prePay(order, openid);
                    if (message.getType() == Message.Type.success) {
                        map.put("tokenId", message.getContent());
                    }
                    map.put("message", message);

                } catch (Exception e) {
                    LOGGER.error(e.getMessage());
                }
            }
        }
        return map;
    }

    @ResponseBody
    @RequestMapping(value = "/rm/notify", method = RequestMethod.POST)
    public String notifyRmPay(HttpServletRequest request) {
        LOGGER.info("ruomai pay notify......");

        try {
            ServletInputStream stream = request.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(stream));
            String line = "";
            StringBuilder sb = new StringBuilder();

            while ((line = br.readLine()) != null) {
                sb.append(line);
            }

            String paramStr = new String(sb.toString());
            LOGGER.info("paramStr=" + paramStr);

            JSONObject json = JSONObject.parseObject(paramStr);
            String returnCode = json.getString("returnCode");
            if (returnCode.equals("0")) {//通讯成功
                String resultCode = json.getString("resultCode");
                if (resultCode.equals("0")) {//交易成功
                    String outTradeNo = json.getString("outTradeNo");
                    String transactionId = json.getString("transactionId");
                    String timeEnd = json.getString("timeEnd");

                    ServOrder order = orderService.findServOrderByOrderNo(outTradeNo);
                    order.setTransactionId(transactionId);
                    order.setTradeState(Constants.TRADE_STATE_SUCCESS);
                    order.setTradeStateDesc("支付成功");
                    order.setTimeEnd(new Date(timeEnd));
                    orderService.updateByPrimaryKey(order);

                    PubDevice device = pubDeviceService.selectByPrimaryKey(order.getDeviceid());
                    //发送出币指令
                    netService.sendClientBuy(device.getImme(), device.getDevicetypeid().intValue(), order.getCashFee(),
                            order.getCoin(), PayConfig.PAY_WECHAT, outTradeNo);
                }
            }

        } catch (IOException e) {
            LOGGER.error(e.getMessage());
            return "error";
        }
        return "success";
    }
*/
}
